"""
剧场详情API服务 - theater_detail.py
修复版：完全匹配前端期望的数据格式
"""

import json
import os
from datetime import datetime
from typing import Dict, List, Any, Optional
from contextlib import asynccontextmanager

from fastapi import FastAPI, HTTPException, Query, Path
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse, FileResponse
from pydantic import BaseModel, Field
import uvicorn

from database import get_mysql_manager

# ==================== 数据模型 ====================

class ApiResponse(BaseModel):
    success: bool
    message: str
    data: Optional[Dict[str, Any]] = None
    error_code: Optional[str] = None

class ExportRequest(BaseModel):
    format: str = Field(default="json", description="导出格式: json, detailed, summary, csv")
    include_chat_data: bool = Field(default=True, description="是否包含聊天数据")
    include_statistics: bool = Field(default=True, description="是否包含统计信息")
    filename: Optional[str] = Field(default=None, description="导出文件名")

# ==================== 核心业务类 ====================

class TheaterDetailManager:
    def __init__(self):
        """初始化剧场详情管理器"""
        try:
            self.mysql_manager = get_mysql_manager()
            print("✅ 数据库连接初始化成功")
        except Exception as e:
            print(f"❌ 数据库连接失败: {e}")
            self.mysql_manager = None

    def get_theater_by_task_id(self, task_id: str) -> Dict[str, Any]:
        """通过task_id获取剧场完整详情 - 🔧 匹配前端数据格式"""
        try:
            if not self.mysql_manager:
                return {"success": False, "error": "数据库未初始化"}

            with self.mysql_manager.get_connection() as connection:
                cursor = connection.cursor(dictionary=True)

                # 1. 获取剧场基本信息
                theater_info = self._get_theater_info_formatted(cursor, task_id)
                if not theater_info:
                    return {
                        "success": False,
                        "error": f"未找到task_id为 {task_id} 的剧场",
                        "query_time": datetime.now().isoformat()
                    }

                theater_id = theater_info['id']

                # 2. 获取角色信息 - 格式化为前端期望格式
                characters = self._get_characters_formatted(cursor, theater_id)

                # 3. 获取剧情节点 - 格式化为前端期望格式
                script_nodes = self._get_script_nodes_formatted(cursor, theater_id)

                # 4. 获取技能池 - 格式化为前端期望格式
                available_skills = self._get_skills_formatted(cursor, theater_id)

                # 5. 获取聊天会话
                chat_sessions = self._get_chat_sessions(cursor, theater_id)

                # 6. 获取聊天消息（最近100条）
                chat_messages = self._get_recent_chat_messages(cursor, theater_id, limit=100)

                # 7. 计算统计信息
                chat_statistics = self._calculate_chat_statistics(cursor, theater_id)

                # 8. 获取生成元数据
                generation_metadata = self._get_generation_metadata(theater_info)

                cursor.close()

                # 🔧 构建与前端完全匹配的数据格式
                theater_detail = {
                    "theater_info": {
                        "title": theater_info.get('title', ''),
                        "description": theater_info.get('description', ''),
                        "era": theater_info.get('era', ''),
                        "location": theater_info.get('location', ''),
                        "createdAt": theater_info.get('created_at', ''),  # 注意字段名
                        "author": theater_info.get('author', ''),
                        "plotSummary": theater_info.get('plot_summary', ''),  # 注意字段名
                        "features": theater_info.get('features', [])
                    },
                    "script_nodes": script_nodes,  # 已格式化
                    "characters": characters,      # 已格式化
                    "available_skills": available_skills,  # 技能字符串数组
                    "chat_sessions": chat_sessions,
                    "recent_chat_messages": chat_messages,
                    "chat_statistics": chat_statistics,
                    "generation_metadata": generation_metadata,
                    "summary": {
                        "total_characters": len(characters),
                        "total_script_nodes": len(script_nodes),
                        "total_skills": len(available_skills),
                        "total_chat_sessions": len(chat_sessions),
                        "total_chat_messages": chat_statistics.get('basic', {}).get('total_messages', 0)
                    }
                }

                return {
                    "success": True,
                    "task_id": task_id,
                    "theater_id": theater_id,
                    "data": theater_detail,
                    "query_time": datetime.now().isoformat()
                }

        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "query_time": datetime.now().isoformat()
            }

    def _get_theater_info_formatted(self, cursor, task_id: str) -> Optional[Dict[str, Any]]:
        """获取剧场基本信息 - 格式化版本"""
        try:
            cursor.execute("""
                SELECT * FROM theaters WHERE task_id = %s LIMIT 1
            """, (task_id,))

            theater = cursor.fetchone()
            if not theater:
                return None

            # 处理JSON字段
            if theater.get('features'):
                try:
                    theater['features'] = json.loads(theater['features'])
                except:
                    theater['features'] = []
            else:
                theater['features'] = []

            # 转换时间格式
            if theater.get('created_at'):
                theater['created_at'] = theater['created_at'].isoformat()
            if theater.get('updated_at'):
                theater['updated_at'] = theater['updated_at'].isoformat()

            return theater

        except Exception as e:
            print(f"❌ 获取剧场信息失败: {e}")
            return None

    def _get_characters_formatted(self, cursor, theater_id: int) -> List[Dict[str, Any]]:
        """获取角色信息 - 🔧 格式化为前端期望格式"""
        try:
            cursor.execute("""
                SELECT 
                    id, character_id, name, description, avatar, 
                    selected_skills, created_at
                FROM characters 
                WHERE theater_id = %s 
                ORDER BY id ASC
            """, (theater_id,))

            characters = cursor.fetchall()

            formatted_characters = []
            for character in characters:
                # 🔧 处理技能数据
                selected_skills = []
                if character.get('selected_skills'):
                    try:
                        parsed_skills = json.loads(character['selected_skills'])
                        if isinstance(parsed_skills, list):
                            selected_skills = [str(skill).strip() for skill in parsed_skills if str(skill).strip()]
                        else:
                            selected_skills = []
                    except:
                        selected_skills = []

                # 🔧 构建前端期望的格式
                formatted_character = {
                    "id": character.get('character_id', ''),  # 使用 character_id 作为 id
                    "name": character.get('name', ''),
                    "description": character.get('description', ''),
                    "avatar": character.get('avatar', ''),
                    "selectedSkills": selected_skills  # 注意字段名：selectedSkills
                }

                formatted_characters.append(formatted_character)

            print(f"✅ 格式化 {len(formatted_characters)} 个角色")
            return formatted_characters

        except Exception as e:
            print(f"❌ 获取角色信息失败: {e}")
            return []

    def _get_script_nodes_formatted(self, cursor, theater_id: int) -> List[Dict[str, Any]]:
        """获取剧情节点 - 🔧 格式化为前端期望格式"""
        try:
            cursor.execute("""
                SELECT 
                    id, node_id, title, content, character_settings, 
                    level, node_order, created_at
                FROM script_nodes 
                WHERE theater_id = %s 
                ORDER BY node_order ASC, id ASC
            """, (theater_id,))

            nodes = cursor.fetchall()

            formatted_nodes = []
            for node in nodes:
                # 🔧 处理角色设置JSON
                character_settings = {}
                if node.get('character_settings'):
                    try:
                        character_settings = json.loads(node['character_settings'])
                    except:
                        character_settings = {}

                # 🔧 构建前端期望的格式
                formatted_node = {
                    "id": node.get('node_id', ''),  # 使用 node_id 作为 id
                    "title": node.get('title', ''),
                    "content": node.get('content', ''),
                    "characterSettings": character_settings,  # 注意字段名：characterSettings
                    "level": node.get('level', 0)
                }

                formatted_nodes.append(formatted_node)

            print(f"✅ 格式化 {len(formatted_nodes)} 个剧情节点")
            return formatted_nodes

        except Exception as e:
            print(f"❌ 获取剧情节点失败: {e}")
            return []

    def _get_skills_formatted(self, cursor, theater_id: int) -> List[str]:
        """获取技能池 - 🔧 返回字符串数组"""
        try:
            cursor.execute("""
                SELECT skill_name
                FROM skills_pool 
                WHERE theater_id = %s 
                ORDER BY skill_order ASC, skill_name ASC
            """, (theater_id,))

            skills_result = cursor.fetchall()

            # 🔧 直接返回技能名称的字符串数组
            skills = [row['skill_name'] for row in skills_result if row['skill_name']]

            print(f"✅ 格式化 {len(skills)} 个技能")
            return skills

        except Exception as e:
            print(f"❌ 获取技能信息失败: {e}")
            return []

    def _get_chat_sessions(self, cursor, theater_id: int) -> List[Dict[str, Any]]:
        """获取聊天会话"""
        try:
            cursor.execute("""
                SELECT 
                    cs.session_id, cs.node_id, cs.node_title, 
                    cs.player_character_id, cs.player_character_name, cs.total_messages, 
                    cs.ai_responses_count, cs.created_at, cs.last_active
                FROM chat_sessions cs
                WHERE cs.theater_id = %s 
                ORDER BY cs.last_active DESC
            """, (theater_id,))

            sessions = cursor.fetchall()

            for session in sessions:
                # 转换时间格式
                if session.get('created_at'):
                    session['created_at'] = session['created_at'].isoformat()
                if session.get('last_active'):
                    session['last_active'] = session['last_active'].isoformat()

            return sessions

        except Exception as e:
            print(f"❌ 获取聊天会话失败: {e}")
            return []

    def _get_recent_chat_messages(self, cursor, theater_id: int, limit: int = 100) -> List[Dict[str, Any]]:
        """获取最近的聊天消息"""
        try:
            cursor.execute("""
                SELECT 
                    cm.id, cm.message_id, cm.character_id, cm.character_name, 
                    cm.message, cm.message_type, cm.created_at as timestamp, 
                    cm.response_time_ms
                FROM chat_messages cm
                JOIN chat_sessions cs ON cm.session_id = cs.session_id
                WHERE cs.theater_id = %s 
                ORDER BY cm.created_at DESC
                LIMIT %s
            """, (theater_id, limit))

            messages = cursor.fetchall()

            for message in messages:
                # 转换时间格式
                if message.get('timestamp'):
                    try:
                        if isinstance(message['timestamp'], str):
                            message['timestamp'] = message['timestamp']
                        else:
                            message['timestamp'] = message['timestamp'].isoformat()
                    except:
                        message['timestamp'] = str(message['timestamp'])

                # 确保id字段正确
                if not message.get('id') and message.get('message_id'):
                    message['id'] = message['message_id']

            return messages

        except Exception as e:
            print(f"❌ 获取聊天消息失败: {e}")
            return []

    def _calculate_chat_statistics(self, cursor, theater_id: int) -> Dict[str, Any]:
        """计算聊天统计信息"""
        try:
            # 基础统计
            cursor.execute("""
                SELECT 
                    COUNT(DISTINCT cs.session_id) as total_sessions,
                    COUNT(DISTINCT cs.node_id) as active_nodes,
                    SUM(cs.total_messages) as total_messages,
                    SUM(cs.ai_responses_count) as total_ai_responses,
                    AVG(cs.total_messages) as avg_messages_per_session,
                    MIN(cs.created_at) as first_session_time,
                    MAX(cs.last_active) as last_session_time
                FROM chat_sessions cs
                WHERE cs.theater_id = %s
            """, (theater_id,))

            basic_stats = cursor.fetchone()

            # 按角色统计
            cursor.execute("""
                SELECT 
                    cm.character_name,
                    COUNT(*) as message_count,
                    COUNT(CASE WHEN cm.message_type = 'dialogue' AND cm.character_id != cs.player_character_id THEN 1 END) as ai_responses,
                    AVG(cm.response_time_ms) as avg_response_time
                FROM chat_messages cm
                JOIN chat_sessions cs ON cm.session_id = cs.session_id
                WHERE cs.theater_id = %s
                GROUP BY cm.character_name
                ORDER BY message_count DESC
            """, (theater_id,))

            character_stats = cursor.fetchall()

            # 按节点统计
            cursor.execute("""
                SELECT 
                    cs.node_title,
                    COUNT(DISTINCT cs.session_id) as session_count,
                    SUM(cs.total_messages) as total_messages,
                    AVG(cs.total_messages) as avg_messages
                FROM chat_sessions cs
                WHERE cs.theater_id = %s
                GROUP BY cs.node_id, cs.node_title
                ORDER BY session_count DESC
            """, (theater_id,))

            node_stats = cursor.fetchall()

            # 时间统计（最近7天的活动）
            cursor.execute("""
                SELECT 
                    DATE(cm.created_at) as date,
                    COUNT(*) as message_count,
                    COUNT(DISTINCT cm.session_id) as session_count
                FROM chat_messages cm
                JOIN chat_sessions cs ON cm.session_id = cs.session_id
                WHERE cs.theater_id = %s 
                AND cm.created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)
                GROUP BY DATE(cm.created_at)
                ORDER BY date DESC
            """, (theater_id,))

            daily_stats = cursor.fetchall()

            # 转换时间格式
            if basic_stats:
                for field in ['first_session_time', 'last_session_time']:
                    if basic_stats.get(field):
                        basic_stats[field] = basic_stats[field].isoformat()

            return {
                "basic": basic_stats or {},
                "by_character": character_stats,
                "by_node": node_stats,
                "daily_activity": daily_stats,
                "calculated_at": datetime.now().isoformat()
            }

        except Exception as e:
            print(f"❌ 计算统计信息失败: {e}")
            return {}

    def _get_generation_metadata(self, theater_info: Dict[str, Any]) -> Dict[str, Any]:
        """获取生成元数据"""
        try:
            metadata = {
                "task_id": theater_info.get('task_id'),
                "creation_time": theater_info.get('created_at'),
                "last_update": theater_info.get('updated_at'),
                "author": theater_info.get('author'),
                "theater_features": theater_info.get('features', []),
                "era": theater_info.get('era'),
                "location": theater_info.get('location'),
                "plot_summary": theater_info.get('plot_summary')
            }

            return metadata

        except Exception as e:
            print(f"❌ 获取生成元数据失败: {e}")
            return {}

    def get_chat_messages_by_session(self, session_id: str, limit: int = 50, offset: int = 0) -> Dict[str, Any]:
        """获取特定会话的聊天消息"""
        try:
            if not self.mysql_manager:
                return {"success": False, "error": "数据库未初始化"}

            with self.mysql_manager.get_connection() as connection:
                cursor = connection.cursor(dictionary=True)

                # 获取消息总数
                cursor.execute("""
                    SELECT COUNT(*) as total 
                    FROM chat_messages 
                    WHERE session_id = %s
                """, (session_id,))

                total = cursor.fetchone()['total']

                # 获取消息列表
                cursor.execute("""
                    SELECT 
                        message_id as id, character_id, character_name, message, 
                        message_type, created_at as timestamp, response_time_ms
                    FROM chat_messages 
                    WHERE session_id = %s
                    ORDER BY message_order ASC, created_at ASC
                    LIMIT %s OFFSET %s
                """, (session_id, limit, offset))

                messages = cursor.fetchall()

                # 处理时间格式
                for message in messages:
                    if message.get('timestamp'):
                        try:
                            if isinstance(message['timestamp'], str):
                                message['timestamp'] = message['timestamp']
                            else:
                                message['timestamp'] = message['timestamp'].isoformat()
                        except:
                            message['timestamp'] = str(message['timestamp'])

                cursor.close()

                return {
                    "success": True,
                    "session_id": session_id,
                    "total": total,
                    "count": len(messages),
                    "limit": limit,
                    "offset": offset,
                    "messages": messages,
                    "query_time": datetime.now().isoformat()
                }

        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "query_time": datetime.now().isoformat()
            }

    def export_theater_data(self, task_id: str, export_request: ExportRequest) -> Dict[str, Any]:
        """导出剧场数据"""
        try:
            # 获取完整剧场数据
            theater_result = self.get_theater_by_task_id(task_id)

            if not theater_result['success']:
                return theater_result

            theater_data = theater_result['data']

            # 生成文件名
            if not export_request.filename:
                timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
                export_request.filename = f"theater_{task_id}_{timestamp}.{export_request.format}"

            # 确保导出目录存在
            export_dir = "theater_exports"
            os.makedirs(export_dir, exist_ok=True)
            file_path = os.path.join(export_dir, export_request.filename)

            # 根据格式生成数据
            if export_request.format == "json":
                export_data = self._format_json_export(theater_data, export_request)
            elif export_request.format == "detailed":
                export_data = self._format_detailed_export(theater_data, export_request)
            elif export_request.format == "summary":
                export_data = self._format_summary_export(theater_data, export_request)
            elif export_request.format == "csv":
                return self._export_csv_format(theater_data, file_path, export_request)
            else:
                return {
                    "success": False,
                    "error": f"不支持的导出格式: {export_request.format}"
                }

            # 写入文件
            with open(file_path, 'w', encoding='utf-8') as f:
                json.dump(export_data, f, ensure_ascii=False, indent=2)

            file_size = os.path.getsize(file_path)

            return {
                "success": True,
                "message": f"剧场数据已导出到 {export_request.filename}",
                "task_id": task_id,
                "filename": export_request.filename,
                "file_path": file_path,
                "format": export_request.format,
                "file_size_bytes": file_size,
                "export_time": datetime.now().isoformat()
            }

        except Exception as e:
            return {
                "success": False,
                "error": str(e)
            }

    def _format_json_export(self, theater_data: Dict[str, Any], export_request: ExportRequest) -> Dict[str, Any]:
        """格式化JSON导出数据"""
        export_data = {
            "export_info": {
                "format": "json",
                "export_time": datetime.now().isoformat(),
                "include_chat_data": export_request.include_chat_data,
                "include_statistics": export_request.include_statistics
            },
            "theater_info": theater_data["theater_info"],
            "characters": theater_data["characters"],
            "script_nodes": theater_data["script_nodes"],
            "available_skills": theater_data["available_skills"],
            "summary": theater_data["summary"]
        }

        if export_request.include_chat_data:
            export_data["chat_sessions"] = theater_data["chat_sessions"]
            export_data["recent_chat_messages"] = theater_data["recent_chat_messages"]

        if export_request.include_statistics:
            export_data["chat_statistics"] = theater_data["chat_statistics"]

        export_data["generation_metadata"] = theater_data["generation_metadata"]

        return export_data

    def _format_detailed_export(self, theater_data: Dict[str, Any], export_request: ExportRequest) -> Dict[str, Any]:
        """格式化详细导出数据"""
        theater_info = theater_data["theater_info"]

        export_data = {
            "export_info": {
                "format": "detailed",
                "export_time": datetime.now().isoformat(),
                "theater_title": theater_info.get('title', ''),
                "task_id": theater_info.get('task_id', '')
            },
            "theater": {
                "basic_info": {
                    "title": theater_info.get('title'),
                    "description": theater_info.get('description'),
                    "era": theater_info.get('era'),
                    "location": theater_info.get('location'),
                    "author": theater_info.get('author'),
                    "features": theater_info.get('features', []),
                    "plotSummary": theater_info.get('plotSummary')
                },
                "content_structure": {
                    "characters": {
                        "count": len(theater_data["characters"]),
                        "details": [
                            {
                                "name": char["name"],
                                "description": char["description"],
                                "selectedSkills": char.get("selectedSkills", []),
                                "id": char.get("id", "")
                            }
                            for char in theater_data["characters"]
                        ]
                    },
                    "script_structure": {
                        "total_nodes": len(theater_data["script_nodes"]),
                        "nodes": [
                            {
                                "title": node["title"],
                                "content": node["content"][:200] + "..." if len(node.get("content", "")) > 200 else node.get("content", ""),
                                "id": node.get("id"),
                                "level": node.get("level")
                            }
                            for node in theater_data["script_nodes"]
                        ]
                    },
                    "skills_system": {
                        "total_skills": len(theater_data["available_skills"]),
                        "skills": theater_data["available_skills"]
                    }
                }
            }
        }

        if export_request.include_chat_data and theater_data["chat_sessions"]:
            export_data["interaction_data"] = {
                "chat_sessions": theater_data["chat_sessions"],
                "recent_messages_sample": theater_data["recent_chat_messages"][:20]
            }

        if export_request.include_statistics:
            export_data["analytics"] = theater_data["chat_statistics"]

        return export_data

    def _format_summary_export(self, theater_data: Dict[str, Any], export_request: ExportRequest) -> Dict[str, Any]:
        """格式化摘要导出数据"""
        theater_info = theater_data["theater_info"]
        summary = theater_data["summary"]

        export_data = {
            "export_info": {
                "format": "summary",
                "export_time": datetime.now().isoformat()
            },
            "theater_summary": {
                "title": theater_info.get('title'),
                "description": theater_info.get('description'),
                "era": theater_info.get('era'),
                "location": theater_info.get('location'),
                "author": theater_info.get('author'),
                "createdAt": theater_info.get('createdAt')
            },
            "content_overview": {
                "characters_count": summary["total_characters"],
                "script_nodes_count": summary["total_script_nodes"],
                "skills_count": summary["total_skills"],
                "main_characters": [
                    {"name": char["name"], "description": char["description"][:100] + "..." if len(char.get("description", "")) > 100 else char.get("description", "")}
                    for char in theater_data["characters"][:5]
                ]
            }
        }

        if export_request.include_statistics and theater_data.get("chat_statistics"):
            chat_stats = theater_data["chat_statistics"].get("basic", {})
            export_data["activity_summary"] = {
                "total_sessions": chat_stats.get("total_sessions", 0),
                "total_messages": chat_stats.get("total_messages", 0),
                "avg_messages_per_session": round(float(chat_stats.get("avg_messages_per_session", 0)), 2) if chat_stats.get("avg_messages_per_session") else 0,
                "first_activity": chat_stats.get("first_session_time"),
                "last_activity": chat_stats.get("last_session_time")
            }

        return export_data

    def _export_csv_format(self, theater_data: Dict[str, Any], file_path: str, export_request: ExportRequest) -> Dict[str, Any]:
        """导出CSV格式数据"""
        import csv

        try:
            with open(file_path, 'w', newline='', encoding='utf-8') as csvfile:
                writer = csv.writer(csvfile)

                # 写入剧场基本信息
                writer.writerow(['=== 剧场基本信息 ==='])
                theater_info = theater_data["theater_info"]
                for key, value in theater_info.items():
                    if key not in ['features']:
                        writer.writerow([key, str(value)])

                writer.writerow([])

                # 写入角色信息
                writer.writerow(['=== 角色信息 ==='])
                writer.writerow(['角色ID', '角色名', '描述', '技能'])
                for char in theater_data["characters"]:
                    writer.writerow([
                        char.get('id', ''),
                        char.get('name', ''),
                        char.get('description', ''),
                        ', '.join(char.get('selectedSkills', []))
                    ])

                writer.writerow([])

                # 写入剧情节点
                writer.writerow(['=== 剧情节点 ==='])
                writer.writerow(['节点ID', '标题', '内容摘要', '级别'])
                for node in theater_data["script_nodes"]:
                    writer.writerow([
                        node.get('id', ''),
                        node.get('title', ''),
                        node.get('content', '')[:500] + '...' if len(node.get('content', '')) > 500 else node.get('content', ''),
                        node.get('level', '')
                    ])

                writer.writerow([])

                # 写入技能信息
                writer.writerow(['=== 技能信息 ==='])
                writer.writerow(['技能名'])
                for skill in theater_data["available_skills"]:
                    writer.writerow([skill])

                if export_request.include_chat_data and theater_data["chat_sessions"]:
                    writer.writerow([])
                    writer.writerow(['=== 聊天会话 ==='])
                    writer.writerow(['会话ID', '节点标题', '角色ID', '消息总数', '创建时间'])
                    for session in theater_data["chat_sessions"]:
                        writer.writerow([
                            session.get('session_id', ''),
                            session.get('node_title', ''),
                            session.get('player_character_id', ''),
                            session.get('total_messages', ''),
                            session.get('created_at', '')
                        ])

            file_size = os.path.getsize(file_path)

            return {
                "success": True,
                "message": f"CSV数据已导出到 {os.path.basename(file_path)}",
                "filename": os.path.basename(file_path),
                "file_path": file_path,
                "format": "csv",
                "file_size_bytes": file_size,
                "export_time": datetime.now().isoformat()
            }

        except Exception as e:
            return {
                "success": False,
                "error": f"CSV导出失败: {str(e)}"
            }

# ==================== 全局变量 ====================

detail_manager = None

# ==================== 生命周期管理 ====================

@asynccontextmanager
async def lifespan(app: FastAPI):
    """FastAPI应用生命周期管理"""
    # 启动时执行
    print("🚀 启动剧场详情API服务...")

    global detail_manager
    try:
        detail_manager = TheaterDetailManager()
        if detail_manager.mysql_manager:
            print("✅ 剧场详情管理器初始化成功")
        else:
            print("❌ 数据库连接失败")
    except Exception as e:
        print(f"❌ 剧场详情管理器初始化失败: {e}")
        detail_manager = None

    yield  # 应用运行期间

    # 关闭时执行
    print("🛑 正在关闭剧场详情API服务...")

    # 关闭数据库连接
    if detail_manager and detail_manager.mysql_manager:
        detail_manager.mysql_manager.close()
        print("✅ 数据库连接已关闭")

    print("✅ 剧场详情API服务已关闭")

# ==================== FastAPI应用 ====================

app = FastAPI(
    title="剧场详情API",
    description="通过task_id获取剧场完整数据的接口服务",
    version="1.0.2",
    docs_url="/docs",
    redoc_url="/redoc",
    lifespan=lifespan
)

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# ==================== API端点 ====================

@app.get("/", response_model=ApiResponse)
async def root():
    """根路径 - 服务信息"""
    return ApiResponse(
        success=True,
        message="剧场详情API服务正在运行",
        data={
            "version": "1.0.2",
            "docs": "/docs",
            "endpoints": {
                "theater_detail": "/theater/{task_id}",
                "chat_messages": "/theater/{task_id}/chat/{session_id}",
                "export": "/theater/{task_id}/export",
                "health": "/health"
            },
            "database_ready": detail_manager is not None and detail_manager.mysql_manager is not None
        }
    )

@app.get("/health", response_model=ApiResponse)
async def health_check():
    """健康检查"""
    try:
        if not detail_manager or not detail_manager.mysql_manager:
            return ApiResponse(
                success=False,
                message="数据库未初始化",
                error_code="DATABASE_NOT_READY"
            )

        # 测试数据库连接
        with detail_manager.mysql_manager.get_connection() as connection:
            cursor = connection.cursor()
            cursor.execute("SELECT COUNT(*) FROM theaters")
            theater_count = cursor.fetchone()[0]
            cursor.close()

        return ApiResponse(
            success=True,
            message="服务正常运行",
            data={
                "status": "healthy",
                "theater_count": theater_count,
                "timestamp": datetime.now().isoformat()
            }
        )
    except Exception as e:
        return ApiResponse(
            success=False,
            message=f"健康检查失败: {str(e)}",
            error_code="HEALTH_CHECK_FAILED"
        )

@app.get("/theater/{task_id}", response_model=ApiResponse)
async def get_theater_detail(
    task_id: str = Path(..., description="剧场任务ID")
):
    """获取剧场完整详情"""
    try:
        if not detail_manager:
            raise HTTPException(status_code=503, detail="服务未初始化")

        result = detail_manager.get_theater_by_task_id(task_id)

        if result['success']:
            return ApiResponse(
                success=True,
                message="获取剧场详情成功",
                data=result
            )
        else:
            if "未找到" in result.get('error', ''):
                raise HTTPException(status_code=404, detail=result['error'])
            else:
                raise HTTPException(status_code=500, detail=result.get('error', '获取剧场详情失败'))

    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=500,
            detail=f"获取剧场详情失败: {str(e)}"
        )

@app.get("/theater/{task_id}/chat/{session_id}", response_model=ApiResponse)
async def get_chat_messages(
    task_id: str = Path(..., description="剧场任务ID"),
    session_id: str = Path(..., description="聊天会话ID"),
    limit: int = Query(50, description="限制返回数量", ge=1, le=500),
    offset: int = Query(0, description="偏移量", ge=0)
):
    """获取特定会话的聊天消息"""
    try:
        if not detail_manager:
            raise HTTPException(status_code=503, detail="服务未初始化")

        result = detail_manager.get_chat_messages_by_session(
            session_id=session_id,
            limit=limit,
            offset=offset
        )

        if result['success']:
            return ApiResponse(
                success=True,
                message="获取聊天消息成功",
                data=result
            )
        else:
            raise HTTPException(
                status_code=500,
                detail=result.get('error', '获取聊天消息失败')
            )

    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=500,
            detail=f"获取聊天消息失败: {str(e)}"
        )

@app.post("/theater/{task_id}/export", response_model=ApiResponse)
async def export_theater_data(
    task_id: str = Path(..., description="剧场任务ID"),
    export_request: ExportRequest = ExportRequest()
):
    """导出剧场数据"""
    try:
        if not detail_manager:
            raise HTTPException(status_code=503, detail="服务未初始化")

        result = detail_manager.export_theater_data(task_id, export_request)

        if result['success']:
            return ApiResponse(
                success=True,
                message="数据导出成功",
                data=result
            )
        else:
            raise HTTPException(
                status_code=500,
                detail=result.get('error', '数据导出失败')
            )

    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=500,
            detail=f"数据导出失败: {str(e)}"
        )

@app.get("/theater/{task_id}/export/{filename}/download")
async def download_export_file(
    task_id: str = Path(..., description="剧场任务ID"),
    filename: str = Path(..., description="文件名")
):
    """下载导出的文件"""
    try:
        file_path = os.path.join("theater_exports", filename)

        if not os.path.exists(file_path):
            raise HTTPException(status_code=404, detail="文件不存在")

        return FileResponse(
            path=file_path,
            filename=filename,
            media_type='application/octet-stream'
        )

    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=500,
            detail=f"文件下载失败: {str(e)}"
        )

@app.get("/theaters", response_model=ApiResponse)
async def get_theaters_summary(
    limit: int = Query(20, description="限制返回数量", ge=1, le=100),
    offset: int = Query(0, description="偏移量", ge=0)
):
    """获取剧场摘要列表"""
    try:
        if not detail_manager or not detail_manager.mysql_manager:
            raise HTTPException(status_code=503, detail="服务未初始化")

        with detail_manager.mysql_manager.get_connection() as connection:
            cursor = connection.cursor(dictionary=True)

            # 获取总数
            cursor.execute("SELECT COUNT(*) as total FROM theaters")
            total = cursor.fetchone()['total']

            # 获取剧场列表
            cursor.execute("""
                SELECT 
                    id, title, description, era, location, author, task_id, created_at,
                    (SELECT COUNT(*) FROM characters WHERE theater_id = theaters.id) as character_count,
                    (SELECT COUNT(*) FROM script_nodes WHERE theater_id = theaters.id) as node_count,
                    (SELECT COUNT(*) FROM chat_sessions WHERE theater_id = theaters.id) as session_count
                FROM theaters 
                ORDER BY created_at DESC
                LIMIT %s OFFSET %s
            """, (limit, offset))

            theaters = cursor.fetchall()

            # 处理时间格式
            for theater in theaters:
                if theater.get('created_at'):
                    theater['created_at'] = theater['created_at'].isoformat()

            cursor.close()

            return ApiResponse(
                success=True,
                message="获取剧场列表成功",
                data={
                    "total": total,
                    "count": len(theaters),
                    "limit": limit,
                    "offset": offset,
                    "theaters": theaters,
                    "query_time": datetime.now().isoformat()
                }
            )

    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=500,
            detail=f"获取剧场列表失败: {str(e)}"
        )

# ==================== 异常处理 ====================

@app.exception_handler(HTTPException)
async def http_exception_handler(request, exc):
    return JSONResponse(
        status_code=exc.status_code,
        content={
            "success": False,
            "message": str(exc.detail),
            "error_code": "HTTP_ERROR"
        }
    )

@app.exception_handler(Exception)
async def general_exception_handler(request, exc):
    print(f"❌ 服务器错误: {exc}")
    return JSONResponse(
        status_code=500,
        content={
            "success": False,
            "message": f"服务器内部错误: {str(exc)}",
            "error_code": "INTERNAL_SERVER_ERROR"
        }
    )

# ==================== 启动配置 ====================

def main():
    """主函数"""
    print("🎭 启动剧场详情API服务...")
    print(f"📖 API文档: http://localhost:8803/docs")
    print(f"🔍 Redoc文档: http://localhost:8803/redoc")
    print("💡 按 Ctrl+C 停止服务")
    print()
    print("🚀 支持的功能:")
    print("   - 📋 剧场详情查询 (/theater/{task_id})")
    print("   - 💬 聊天消息查询 (/theater/{task_id}/chat/{session_id})")
    print("   - 📤 数据导出功能 (/theater/{task_id}/export)")
    print("   - 📁 文件下载 (/theater/{task_id}/export/{filename}/download)")
    print("   - 📊 剧场列表摘要 (/theaters)")
    print("   - 🏥 健康状态检查 (/health)")
    print()
    print("📁 数据存储:")
    print(f"   - MySQL数据库: theam.theaters")
    print(f"   - 导出文件目录: theater_exports/")
    print()
    print("🔧 修复内容:")
    print("   - 🎯 完全匹配前端数据格式")
    print("   - 🔧 字段名称统一 (selectedSkills, characterSettings)")
    print("   - 📋 技能返回字符串数组格式")
    print("   - 🗂️ 剧场信息字段名映射 (createdAt, plotSummary)")
    
    return True

if __name__ == "__main__":
    if main():
        uvicorn.run(
            "theater_detail:app",
            host="0.0.0.0",
            port=8803,
            reload=True,
            log_level="info",
            access_log=True
        )
